----------------------------------------------------------------
-- Global Variables
----------------------------------------------------------------

ServerSelectWindow =
{
    SORT_ASCENDING   = true,
    SORT_DESCENDING  = false,
    MAXIMUM_SORT     = 6,
    currentSort      = 2,
    sortButtonData   = {},
    gotServerList    = false,
}

ServerSelectWindow.BOTH_REALM_OPTIONS = 1
ServerSelectWindow.ORDER_ONLY = 2
ServerSelectWindow.DESTRUCTION_ONLY = 3

ServerSelectWindow.serverList = {}
ServerSelectWindow.selectedServer = 1
ServerSelectWindow.preselectedServer = 1
ServerSelectWindow.preselectedServerRealm = ServerSelectWindow.ORDER_ONLY
ServerSelectWindow.preselectedServerList = {}
ServerSelectWindow.popBonusServer = 1
ServerSelectWindow.popBonusServerRealm = ServerSelectWindow.BOTH_REALM_OPTIONS
ServerSelectWindow.popBonusCancelMeansCancel = true
ServerSelectWindow.showLegacyServers = false

ServerSelectWindow.PopulationDensityLow = 0
ServerSelectWindow.PopulationDensityMed = 1
ServerSelectWindow.PopulationDensityHigh = 2
ServerSelectWindow.preselectedFullToLowImbalance    = 10   -- the highest priority imbalance is a full pop to low pop
ServerSelectWindow.preselectedHighToLowImbalance    = 9
ServerSelectWindow.preselectedMedToLowImbalance     = 8
ServerSelectWindow.preselectedLowToLowImbalance     = 7
ServerSelectWindow.preselectedFullToMedImbalance    = 6
ServerSelectWindow.preselectedHighToMedImbalance    = 5
ServerSelectWindow.preselectedMedToMedImbalance     = 4
ServerSelectWindow.preselectedFullToHighImbalance   = 3
ServerSelectWindow.preselectedHighToHighImbalance   = 2
ServerSelectWindow.preselectedFullToFullImbalance   = 1

ServerSelectWindow.sortButtonData[1] = { label = StringTables.Pregame.LABEL_BUTTON_SERVER_SELECT_NAME,                      direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
ServerSelectWindow.sortButtonData[2] = { label = StringTables.Pregame.LABEL_BUTTON_SERVER_SELECT_CHARACTER_COUNT,           direction = ServerSelectWindow.SORT_ASCENDING,  active = true,  }
ServerSelectWindow.sortButtonData[3] = { label = StringTables.Pregame.LABEL_BUTTON_SERVER_SELECT_TYPE,                      direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
ServerSelectWindow.sortButtonData[4] = { label = StringTables.Pregame.LABEL_BUTTON_SERVER_SELECT_LOCATION,                  direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
ServerSelectWindow.sortButtonData[5] = { label = StringTables.Pregame.LABEL_BUTTON_SERVER_SELECT_LANGUAGE,                  direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
ServerSelectWindow.sortButtonData[6] = { label = "",                                                                        direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
ServerSelectWindow.sortButtonData[7] = { label = StringTables.Pregame.LABEL_BUTTON_SERVER_SELECT_ORDER_POPULATION,          direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
ServerSelectWindow.sortButtonData[8] = { label = "",                                                                        direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
ServerSelectWindow.sortButtonData[9] = { label = StringTables.Pregame.LABEL_BUTTON_SERVER_SELECT_DESTRUCTION_POPULATION,    direction = ServerSelectWindow.SORT_ASCENDING,  active = false, }
-- keep track of the 2 icon buttons, that means if more buttons get added these should be updated if needed
ServerSelectWindow.iconButtons = {6, 8} 

ServerSelectWindow.autoLoggedIn = false       -- used to determine if we need to display the welcome text during character creation

ServerSelectWindow.popBonusServers = {}
ServerSelectWindow.trialUserServers = {}

ServerSelectWindow.trialPlayer = false
ServerSelectWindow.buddiedPlayer = false
ServerSelectWindow.trialPlayerServer = nil


----------------------------------------------------------------
-- Local Variables
----------------------------------------------------------------
ServerSelectWindow.bNeedTwoAccepts = false

----------------------------------------------------------------
-- Functions
----------------------------------------------------------------

-- OnInitialize Handler
function ServerSelectWindow.Initialize()
    -- initialize the auto logged in boolean
    ServerSelectWindow.autoLoggedIn = false

    WindowRegisterEventHandler( "ServerSelectWindow", SystemData.Events.PLAYER_DATA_RESPONSE, "ServerSelectWindow.PlayerDataResponse")
    WindowRegisterEventHandler( "ServerSelectWindow", SystemData.Events.SERVER_LIST_RESPONSE, "ServerSelectWindow.ServerListResponse")
    WindowRegisterEventHandler( "ServerSelectWindow", SystemData.Events.INTERFACE_RELOADED,   "ServerSelectWindow.RefreshList")

    LabelSetText("ServerSelectWindowLoadingLabel", GetPregameString( StringTables.Pregame.LABEL_LOADING_SERVER_LIST ) )

    ButtonSetCheckButtonFlag( "ServerSelectWindowShowLegacy", true )
    ButtonSetText( "ServerSelectWindowShowLegacy", GetPregameString( StringTables.Pregame.LABEL_MORE ) )

    ServerSelectWindow.gotServerList = false
    ServerSelectWindow.InitializeButtons()
    ServerSelectWindow.RefreshPlayerData()
    ServerSelectWindow.RefreshList()
    ServerSelectWindow.ManageProgressWindow()

    -- if the player is on a trial we want to push them to the trial user servers
    if ServerSelectWindow.SendToTrialUserServer()
    then
        -- sense we are going to a trial server we'll hide the preselected window
        WindowSetShowing("ServerSelectWindowPreSelectedWindow", false)
        -- and the pop bonus window
        WindowSetShowing("ServerSelectWindowPopBonusWindow", false)
        ServerSelectWindow.SelectTrialUserServer()
    -- if there are servers that have a population bonus we always want to offer them to the user
    elseif ServerSelectWindow.GetPopBonusServer() == -1
    then
        -- since there weren't any population bonus servers we will hide the window
        WindowSetShowing("ServerSelectWindowPopBonusWindow", false)
        ServerSelectWindow.InitPreSelect()
    else
        -- sense we are showing the population bonus server we will hide the pre-selected window
        WindowSetShowing("ServerSelectWindowPreSelectedWindow", false)
        -- true is passed here so that we know to go to the server select window if they decline the server
        ServerSelectWindow.ShowPopBonusServer(true)
    end
end

function ServerSelectWindow.Shutdown()
    WindowUnregisterEventHandler( "ServerSelectWindow", SystemData.Events.INTERFACE_RELOADED    )
    WindowUnregisterEventHandler( "ServerSelectWindow", SystemData.Events.SERVER_LIST_RESPONSE  )
end

function ServerSelectWindow.RefreshPlayerData()
    ServerSelectWindow.trialPlayer, ServerSelectWindow.buddiedPlayer = GetAccountData()
end

function ServerSelectWindow.RefreshList()
    -- Just in case we are trying to auto-log someone into a server that is down or goes down we want
    -- the server list to be shown so they don't have to shut down and restart the game
    WindowSetShowing("ServerSelectWindow", true)
    
    local tempList = GetServerList()
    ServerSelectWindow.serverList = {}

    for index, data in pairs(tempList)
    do
        -- show the server if it is not a legacy server and not a retired server
        -- or if it is not retired, and is a legacy server, and we are set to showLegacyServers
        -- or if the server is legacy or retired, but we have a character on it
        if( ( not data.legacy and not data.retired) or 
            ( not data.retired and data.legacy and ServerSelectWindow.showLegacyServers ) or 
            ( (data.legacy or data.retired) and (data.characterCount ~= 0) )  ) 
        then
            table.insert(ServerSelectWindow.serverList, data)
        end
    end

    WindowSetShowing("ServerSelectWindowLoadingLabel", (#ServerSelectWindow.serverList == 0))
    if ( ServerSelectWindow.gotServerList )
    then
        LabelSetText("ServerSelectWindowLoadingLabel", GetPregameString( StringTables.Pregame.LABEL_EMPTY_SERVER_LIST ) )
    end
    
    ServerSelectWindow.SetSortFunction()
    table.sort(ServerSelectWindow.serverList, ServerSelectWindow.FlexibleSort)

    -- reset the bonus server list
    ServerSelectWindow.popBonusServers = {}
    -- reset the trial user server list
    ServerSelectWindow.trialUserServers = {}

    local displayOrder = {}
    local popBonusIndex = 1
    local trialUserIndex = 1
    for index, data in pairs(ServerSelectWindow.serverList)
    do
        local trialServerInserted = false
        
        -- if we are supposed to redirect players to this server and the server is "local" add it to the list
        -- adding check so that we only redirect you to a server with the same language as you
        -- only add the server if it's online
        if (data.redirect and (data.localeDistance == 0) and data.sameLanguage and data.online)
        then
            ServerSelectWindow.popBonusServers[popBonusIndex] = index
            popBonusIndex = popBonusIndex + 1
        end
        
        -- this is a list for servers that the trial users are sent to
        -- this is potentially a duplicate list to the redirect server list but I want to be able to easily
        -- seperate them
        -- added the redirect flag now because a trial server must be flagged for redirect if we are going to
        -- push users to it
        if (data.redirect and data.trialServer and (data.localeDistance == 0) and data.sameLanguage)
        then
            ServerSelectWindow.trialUserServers[trialUserIndex] = index

            -- If the player is a trial player but not a buddied player insert the
            -- server to the top of the list
            if( ServerSelectWindow.trialPlayer and not ServerSelectWindow.buddiedPlayer )
            then
                table.insert(displayOrder, trialUserIndex, index)
                trialServerInserted = true
            end            
            
            trialUserIndex = trialUserIndex + 1
        end
        
        -- Insert the server index if the player is not a trial player or they are a buddied trial player
        if( not trialServerInserted )
        then
            table.insert(displayOrder, index)
        end
    end
    
    ListBoxSetDisplayOrder("ServerSelectWindowList", displayOrder)
end

function ServerSelectWindow.PlayerDataResponse()
    ServerSelectWindow.RefreshPlayerData()
end

function ServerSelectWindow.ServerListResponse()
    ServerSelectWindow.gotServerList = true
    ServerSelectWindow.RefreshList()

    -- no reason for these buttons to be showing if we are still getting updates.
    if (DoesWindowExist("LoginProgressWindow")) then
        LoginProgressWindow.HideErrorButtons()
    end
end

function ServerSelectWindow.InitializeButtons()
    ButtonSetText( "ServerSelectWindowSelectButton", GetPregameString( StringTables.Pregame.LABEL_BUTTON_PRELOGIN_SERVER_SELECT         ) )

    for index, data in pairs(ServerSelectWindow.sortButtonData)
    do
        local buttonName = "ServerSelectWindowSortButton"..index
        -- the buttons for the population bonus don't have label text so we will skip them
        if data.label ~= ""
        then
            ButtonSetText( buttonName, GetPregameString( data.label ) )
        end
        -- hide the icon for all the buttons
        WindowSetShowing("ServerSelectWindowSortButton"..index.."IconBase", false)
    end

    -- 2 of the buttons have icons on them instead of text, so show them and set the icons
    WindowSetShowing("ServerSelectWindowSortButton"..ServerSelectWindow.iconButtons[1].."IconBase", true)
    DynamicImageSetTextureSlice( "ServerSelectWindowSortButton"..ServerSelectWindow.iconButtons[1].."IconBase", "RealmBonus-Order" )
    WindowSetShowing("ServerSelectWindowSortButton"..ServerSelectWindow.iconButtons[2].."IconBase", true)
    DynamicImageSetTextureSlice( "ServerSelectWindowSortButton"..ServerSelectWindow.iconButtons[2].."IconBase", "RealmBonus-Destruction" )

    -- Disable buttons that we don't know what do yet.
    ButtonSetDisabledFlag( "ServerSelectWindowSortButton1", false )
    ButtonSetDisabledFlag( "ServerSelectWindowSortButton2", false )
    ButtonSetDisabledFlag( "ServerSelectWindowSortButton3", false )
    ButtonSetDisabledFlag( "ServerSelectWindowSortButton4", false )
    ButtonSetDisabledFlag( "ServerSelectWindowSortButton5", false )
    ButtonSetDisabledFlag( "ServerSelectWindowSortButton6", false )
    
    ServerSelectWindow.RefreshSortButtons()
end

function ServerSelectWindow.RefreshSortButtons()
    for index, data in pairs(ServerSelectWindow.sortButtonData)
    do
        local buttonName = "ServerSelectWindowSortButton"..index
        local isEnabled  = (not ButtonGetDisabledFlag( buttonName )) and data.active
        local isUp       = (data.direction == ServerSelectWindow.SORT_DESCENDING)
        
        WindowSetShowing( buttonName.."UpArrow",   isEnabled and isUp )
        WindowSetShowing( buttonName.."DownArrow", isEnabled and not isUp )
    end
end

function ServerSelectWindow.PopulateList()

    -- DEBUG(L"ServerSelectWindow.PopulateList()")

    -- Post-process any conditional formatting
    for row, data in ipairs(ServerSelectWindowList.PopulatorIndices)
    do
        local serverData = ServerSelectWindow.serverList[data]
        local rowFrame   = "ServerSelectWindowListRow"..row

        local isSelectedRow = (ServerSelectWindow.selectedServer == ListBoxGetDataIndex("ServerSelectWindowList", row))
        local ruleset = serverData.ruleset
        local rulesetString = L""
        if serverData.rulesetCore
        then
            rulesetString = GetPregameString( StringTables.Pregame.LABEL_RULESET_CORE )
        elseif serverData.rulesetRolePlaying and serverData.rulesetOpenRvR
        then
            rulesetString = GetPregameString( StringTables.Pregame.LABEL_RULESET_OPEN_RVR_RP )
        elseif serverData.rulesetOpenRvR
        then
            rulesetString = GetPregameString( StringTables.Pregame.LABEL_RULESET_OPEN_RVR )
        elseif serverData.rulesetRolePlaying
        then
            rulesetString = GetPregameString( StringTables.Pregame.LABEL_RULESET_ROLE_PLAY )
        end

        LabelSetText(rowFrame.."Name",           L""..serverData.name)

        -- set the default text for the character count
        LabelSetText(rowFrame.."CharacterCount", L""..serverData.characterCount)

        -- if there are characters
        if (serverData.characterCount > 0)
        then
            -- if the character is an order character append an order char to the character count
            if serverData.orderChars
            then
                charsLabel = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_NUMBER_OF_CHARS, { L""..serverData.characterCount, GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_NUMBER_OF_CHARS_ORDER ) } )
                LabelSetText(rowFrame.."CharacterCount", charsLabel)
            elseif serverData.destructionChars
            then
                charsLabel = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_NUMBER_OF_CHARS, { L""..serverData.characterCount, GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_NUMBER_OF_CHARS_DESTRUCTION ) } )
                LabelSetText(rowFrame.."CharacterCount", charsLabel)
            end
        end

        LabelSetText(rowFrame.."Type",           rulesetString )
        LabelSetText(rowFrame.."Location",       GetStringFromTable( "ServerLocation", StringTables.ServerLocation[serverData.region]) )
        LabelSetText(rowFrame.."Language",       GetStringFromTable( "ServerLanguage", serverData.language) )

        -- server population density is now sent down from the server: 0 = low, 1 = med, 2 = high, 2 & a queue = full
        LabelSetText(rowFrame.."Population", ServerSelectWindow.GetPopulationLabel(serverData.orderPopulationDensity, serverData.orderPopulationQueue))
        LabelSetText(rowFrame.."DestructionPopulation", ServerSelectWindow.GetPopulationLabel(serverData.destructionPopulationDensity, serverData.destructionPopulationQueue))

        -- set the icon and then show/hide it based on if there is a non-zero bonus for order
        DynamicImageSetTextureSlice( rowFrame.."OrderIconBase", "RealmBonus-Order" )
        WindowSetShowing(rowFrame.."OrderIconBase", (serverData.orderBonus ~= 0))

        -- set the icon and then show/hide it based on if there is a non-zero bonus for destruction
        DynamicImageSetTextureSlice( rowFrame.."DestructionIconBase", "RealmBonus-Destruction" )
        WindowSetShowing(rowFrame.."DestructionIconBase", (serverData.destructionBonus ~= 0))

        local isOnline = serverData.online

        local serverDisallowTrialPlayer = ServerSelectWindow.trialPlayer and
                                          not ServerSelectWindow.buddiedPlayer and
                                          not serverData.trialServer and
                                          serverData.characterCount == 0
                                               
        -- if the player is a trial player, not a buddied player, and this is not a trial server, and the account has no characters on it then
        -- we will need to grey out all the text
        if ( serverDisallowTrialPlayer )
        then
            LabelSetTextColor(rowFrame.."Name", DefaultColor.MEDIUM_GRAY.r, DefaultColor.MEDIUM_GRAY.g, DefaultColor.MEDIUM_GRAY.b)
            LabelSetTextColor(rowFrame.."CharacterCount", DefaultColor.MEDIUM_GRAY.r, DefaultColor.MEDIUM_GRAY.g, DefaultColor.MEDIUM_GRAY.b)
            LabelSetTextColor(rowFrame.."Type", DefaultColor.MEDIUM_GRAY.r, DefaultColor.MEDIUM_GRAY.g, DefaultColor.MEDIUM_GRAY.b)
            LabelSetTextColor(rowFrame.."Location", DefaultColor.MEDIUM_GRAY.r, DefaultColor.MEDIUM_GRAY.g, DefaultColor.MEDIUM_GRAY.b)
            LabelSetTextColor(rowFrame.."Population", DefaultColor.MEDIUM_GRAY.r, DefaultColor.MEDIUM_GRAY.g, DefaultColor.MEDIUM_GRAY.b)
            LabelSetTextColor(rowFrame.."DestructionPopulation", DefaultColor.MEDIUM_GRAY.r, DefaultColor.MEDIUM_GRAY.g, DefaultColor.MEDIUM_GRAY.b)
        -- elseif the server is online
        elseif isOnline 
        then
            LabelSetTextColor(rowFrame.."Name", DefaultColor.WHITE.r, DefaultColor.WHITE.g, DefaultColor.WHITE.b)
        else
            LabelSetTextColor(rowFrame.."Name", DefaultColor.MEDIUM_GRAY.r, DefaultColor.MEDIUM_GRAY.g, DefaultColor.MEDIUM_GRAY.b)
        end

        ButtonSetStayDownFlag( rowFrame, true )
        ButtonSetPressedFlag( rowFrame, isSelectedRow and isOnline )
        -- if the server isn't only or the server is a non-trial server and the player is a non-buddied trial player
        ButtonSetDisabledFlag( rowFrame, not isOnline or serverDisallowTrialPlayer)
    end

end

----------------------------------------------------------------
-- Event handlers
----------------------------------------------------------------
function ServerSelectWindow.ClickServerButton()
    local index = WindowGetId(SystemData.ActiveWindow.name)
    --DEBUG(L"ServerSelectWindow.ClickServerButton()")
    if not ButtonGetDisabledFlag(SystemData.ActiveWindow.name)
    then
        ServerSelectWindow.selectedServer = ListBoxGetDataIndex("ServerSelectWindowList", index)
        
        -- DEBUG(L"  Server #"..ServerSelectWindow.selectedServer)  

        ServerSelectWindow.RefreshList()
    -- if we are a non-buddied trial player we want to popup a window directing the player to upgrade his account to get to the server
    elseif  (ServerSelectWindow.trialPlayer) and
            (not ServerSelectWindow.buddiedPlayer) and
            (not ServerSelectWindow.serverList[ListBoxGetDataIndex("ServerSelectWindowList", index)].trialServer)

    then
        ServerSelectWindow.ShowUpgradeOption()
    end
    ServerSelectWindow.VerifyServer()
end

-- need to move the button press up a level so that I can add extra popups!
-- removed extra popups but I'll keep it at this level just in case we want to add them back in later
function ServerSelectWindow.SelectServerButton()
    -- if the button is disabled we don't want to do anything
    if (ButtonGetDisabledFlag("ServerSelectWindowSelectButton"))
    then
        return
    end
    ServerSelectWindow.SelectServer()
end

function ServerSelectWindow.SelectServer()
    -- DEBUG(L"ServerSelectWindow.SelectServer()")
    -- DEBUG(L"  "..ServerSelectWindow.selectedServer)

    -- if the server is retired, we do not let them login, we instead show a popup
    if( ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].retired )
    then
        -- just in case the window doesn't exist
        if (DoesWindowExist("EA_Window_Transfer")) then
            EA_Window_TransferPopup.UpdateServerText( EA_Window_TransferPopup.RETIRED_SERVER )
            EA_Window_TransferPopup.Show()
        end
    
    -- if the rule set is role playing and open RvR we need to get them to agree to both the RP and open RvR addendum
    elseif ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].rulesetRolePlaying and 
        ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].rulesetOpenRvR
    then
        if (DoesWindowExist("EA_Window_OpenRvR")) then
            -- we need to get 2 accepts before we can log into the server
            ServerSelectWindow.bNeedTwoAccepts = true
            EA_Window_OpenRvRPopup.Show()
        end
    elseif ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].rulesetRolePlaying
    then
        if (DoesWindowExist("EA_Window_RolePlay")) then
            -- just to be safe, lets make sure this is false since we only need 1 accept to log into the server
            ServerSelectWindow.bNeedTwoAccepts = false
            EA_Window_RolePlayPopup.Show()
        end
    -- or if the ruleset is open rvr we need to get them to agree to the open rvr addendum
    elseif ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].rulesetOpenRvR
    then
        if (DoesWindowExist("EA_Window_OpenRvR")) then
            -- just to be safe, lets make sure this is false since we only need 1 accept to log into the server
            ServerSelectWindow.bNeedTwoAccepts = false
            EA_Window_OpenRvRPopup.Show()
        end
    -- otherwise send them into the server
    else
        -- set the pre-selected server to both realms
        PregameSetPreSelectedServerRealm(ServerSelectWindow.BOTH_REALM_OPTIONS)
        SelectServer(ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].id)
    end
end

-- if we need the user to agree to an addendum we need a way to send them to the server after wards
-- well lucky us... here it is!
function ServerSelectWindow.SelectServerAddendumAccepted()
    -- if we need both addendums to be accepted, i.e. we have a rvr/rp server
    if ServerSelectWindow.bNeedTwoAccepts
    then
        -- since we start with the RvR addendum we'll launch the RP one now and
        -- set the need 2 bool to false
        if (DoesWindowExist("EA_Window_RolePlay")) then
            ServerSelectWindow.bNeedTwoAccepts = false
            EA_Window_RolePlayPopup.Show()
        end
    else
        -- set the pre-selected server to both realms
        PregameSetPreSelectedServerRealm(ServerSelectWindow.BOTH_REALM_OPTIONS)
        SelectServer(ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].id)
    end
end

----------------------------------------------------------------
-- Sorting
----------------------------------------------------------------
function ServerSelectWindow.ChangeSorting()
    -- Update the sort buttons
    local buttonIndex = WindowGetId( SystemData.ActiveWindow.name )
    
    if ( ButtonGetDisabledFlag( SystemData.ActiveWindow.name ) )
    then
        return
    end
    
    for index, data in pairs(ServerSelectWindow.sortButtonData)
    do
        if (index == buttonIndex)
        then
            if (data.active == true)
            then
                data.direction = not data.direction
            else
                data.active = true
                ServerSelectWindow.currentSort = index
            end
        else
            data.active = false
        end
    end
    
    ServerSelectWindow.RefreshList()
    ServerSelectWindow.RefreshSortButtons()
end

function ServerSelectWindow.SetSortFunction()
    for index, data in pairs(ServerSelectWindow.sortButtonData)
    do
        if (data.active == true)
        then
            ServerSelectWindow.currentSort = index
        end
    end
    
    -- DEBUG(L"  ServerSelectWindow.currentSort = "..ServerSelectWindow.currentSort)
end

function ServerSelectWindow.FlexibleSort(a, b)
    if (a == nil)
    then
        return false
    end
    
    if (b == nil)
    then
        return true
    end
    
    for index, data in pairs(ServerSelectWindow.sortButtonData)
    do
        if (index == ServerSelectWindow.currentSort)
        then
            if (data.active == true)
            then
                if (index == 1)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.ServerSort(a, b)
                    else
                        return ServerSelectWindow.ServerSort(b, a)
                    end
                elseif (index == 2)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.CharsSort(a, b)
                    else
                        return ServerSelectWindow.CharsSort(b, a)
                    end
                elseif (index == 3)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.RuleSetSort(a, b)
                    else
                        return ServerSelectWindow.RuleSetSort(b, a)
                    end
                elseif (index == 4)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.LocSort(a, b)
                    else
                        return ServerSelectWindow.LocSort(b, a)
                    end
                elseif (index == 5)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.OrderBonusSort(a, b)
                    else
                        return ServerSelectWindow.OrderBonusSort(b, a)
                    end
                elseif (index == 6)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.OrderPopSort(a, b)
                    else
                        return ServerSelectWindow.OrderPopSort(b, a)
                    end
                elseif (index == 7)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.DestructionBonusSort(a, b)
                    else
                        return ServerSelectWindow.DestructionBonusSort(b, a)
                    end
                elseif (index == 8)
                then
                    if ( data.direction )
                    then
                        return ServerSelectWindow.DestructionPopSort(a, b)
                    else
                        return ServerSelectWindow.DestructionPopSort(b, a)
                    end
                end
            end
        end
    end
    
    return false
end

function ServerSelectWindow.AlphabeticalSort(a, b)
    return (WStringsCompare(a, b) < 0)
end

-- ok, this sorts the higher above the lower number
function ServerSelectWindow.NumericalSort(a, b)
    return a > b
end

function ServerSelectWindow.ServerSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        return ServerSelectWindow.AlphabeticalSort(a.name, b.name)
    end
end

function ServerSelectWindow.CharsSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        -- if the character count is the same we will go to the next step in the sorting heirarchey, 
        -- the server location in relation to the player
        if (a.characterCount == b.characterCount)
        then
            return ServerSelectWindow.LocSort(a, b)
        else
            return ServerSelectWindow.NumericalSort(a.characterCount, b.characterCount)
        end
    end
end

function ServerSelectWindow.RuleSetSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    -- if both servers have the same ruleset then we need to use the next step in the sorting heirarchey,
    -- the concurrent population sort
    elseif (a.rulesetCore and a.rulesetCore) or (a.rulesetOpenRvR and a.rulesetOpenRvR) or (a.rulesetRolePlaying and a.rulesetRolePlaying)
    then
        return ServerSelectWindow.ConcurrentPopSort(a, b)
    -- if the first server is a hardcore server then it is less than or equal to the other one
    elseif a.rulesetCore
    then
        return true
    -- if the second server is hardcore then the first server is not less than the second one
    elseif b.rulesetCore
    then
        return false
    -- if the first server is an open rvr server then it is less than or equal to the other one
    elseif a.rulesetOpenRvR
    then
        return true
    -- if the second server is an open rvr then the first server is not less than the second one
    elseif b.rulesetOpenRvR
    then
        return false
    -- if the first server is a role playing server then it is less than or equal to the other one
    elseif a.rulesetRolePlaying
    then
        return true
    end

    -- we don't need to check for the second server on the last check because it would be false anyway
    -- otherwise return false
    return false
end

function ServerSelectWindow.LocSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        -- if the location distance is the same we need to use the next step in the sort heirarchey,
        -- the rule set
        if (a.localeDistance == b.localeDistance)
        then
            return ServerSelectWindow.RuleSetSort(a, b)
        else
            -- need to sort the lower number first so need to swap these here
            return ServerSelectWindow.NumericalSort(b.localeDistance, a.localeDistance)
        end
    end
end

function ServerSelectWindow.ConcurrentPopSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        -- if the servers have the same concurrent population we need to use the next sort in the heirarchey,
        -- the server name
        if (ServerSelectWindow.GetConcurrentPop(a) == ServerSelectWindow.GetConcurrentPop(b))
        then
            return ServerSelectWindow.ServerSort(a, b)
        else
            -- need to sort the higher number first now
            return ServerSelectWindow.NumericalSort(ServerSelectWindow.GetConcurrentPop(a), ServerSelectWindow.GetConcurrentPop(b))
        end
    end
end

function ServerSelectWindow.OrderPopSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        -- if the servers have the same order population density we need to use the next sort in the heirarchey,
        -- the server name
        if (a.orderPopulationDensity == b.orderPopulationDensity)
        then
            return ServerSelectWindow.ServerSort(a, b)
        else
            -- need to sort the lower number first so need to swap these here
            return ServerSelectWindow.NumericalSort(b.orderPopulationDensity, a.orderPopulationDensity)
        end
    end
end

function ServerSelectWindow.DestructionPopSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        -- if the servers have the same destruction population density we need to use the next sort in the heirarchey,
        -- the server name
        if (a.destructionPopulationDensity == b.destructionPopulationDensity)
        then
            return ServerSelectWindow.ServerSort(a, b)
        else
            -- need to sort the lower number first so need to swap these here
            return ServerSelectWindow.NumericalSort(b.destructionPopulationDensity, a.destructionPopulationDensity)
        end
    end
end

function ServerSelectWindow.OrderBonusSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        -- if the servers have the same order population density we need to use the next sort in the heirarchey,
        -- the server name
        if (a.orderBonus == b.orderBonus)
        then
            return ServerSelectWindow.ServerSort(a, b)
        else
            return ServerSelectWindow.NumericalSort(a.orderBonus, b.orderBonus)
        end
    end
end

function ServerSelectWindow.DestructionBonusSort(a, b)
    if (a.online and not b.online)
    then
        return true
    elseif (b.online and not a.online)
    then
        return false
    else
        -- if the servers have the same destruction population density we need to use the next sort in the heirarchey,
        -- the server name
        if (a.destructionBonus == b.destructionBonus)
        then
            return ServerSelectWindow.ServerSort(a, b)
        else
            return ServerSelectWindow.NumericalSort(a.destructionBonus, b.destructionBonus)
        end
    end
end

function ServerSelectWindow.ManageProgressWindow()
    if (DoesWindowExist("LoginProgressWindow")) then
        WindowSetShowing("LoginProgressWindow", true)
        LoginProgressWindow.StartLobbyLogin()
        LoginProgressWindow.HideErrorButtons()
    end
end

function ServerSelectWindow.HasCharacters()
    -- since we aren't sure that we have a valid server list we will set the return variable to true so that the
    -- pre-selected server window doesn't popup with no info
    local bRetVal = true
    for index, serverData in pairs(ServerSelectWindow.serverList)
    do
        -- now that we know we have servers let's flip the return value
        bRetVal = false

        -- if this server has characters then the player has existing characters so we'll return true
        if serverData.characterCount > 0
        then
            return true
        end

        -- we only want to add the server if it is the same language as the user, is online, and is the core ruleset
        if serverData.sameLanguage and serverData.online and serverData.rulesetCore
        then
            ServerSelectWindow.preselectedServerList[index] = {}
            ServerSelectWindow.preselectedServerList[index].imbalance = 0

            -- a full population density with a low population density
            if (((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityLow) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.destructionPopulationQueue ~= 0)) or
                ((serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityLow) and (serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.orderPopulationQueue ~= 0)))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedFullToLowImbalance
            -- high to low density
            elseif (((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityLow) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityHigh)) or
                ((serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityLow) and (serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityHigh)))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedHighToLowImbalance
            -- med to low density
            elseif (((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityLow) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityMed)) or
                ((serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityLow) and (serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityMed)))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedMedToLowImbalance
            -- low to low density
            elseif ((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityLow) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityLow))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedLowToLowImbalance
            -- full to med density
            elseif (((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityMed) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.destructionPopulationQueue ~= 0)) or
                ((serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityMed) and (serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.orderPopulationQueue ~= 0)))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedFullToMedImbalance
            -- high to med density
            elseif (((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityMed) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityHigh)) or
                ((serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityMed) and (serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityHigh)))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedHighToMedImbalance
            -- med to med density
            elseif ((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityMed) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityMed))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedMedToMedImbalance
            -- full to high density
            elseif(((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.orderPopulationQueue == 0) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.destructionPopulationQueue ~= 0)) or
                ((serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.destructionPopulationQueue == 0) and (serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.orderPopulationQueue ~= 0)))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedFullToHighImbalance
            -- high to high density
            elseif ((serverData.orderPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.orderPopulationQueue == 0) and (serverData.destructionPopulationDensity == ServerSelectWindow.PopulationDensityHigh) and (serverData.destructionPopulationQueue == 0))
            then
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedHighToHighImbalance
            -- and last but not least full to full density
            else
                ServerSelectWindow.preselectedServerList[index].imbalance = ServerSelectWindow.preselectedFullToFullImbalance
            end
        end
    end
    
    return false
end

function ServerSelectWindow.DeterminePreSelect()
    if not ServerSelectWindow.HasCharacters()
    then
        -- set the pre-selected server's ID
        ServerSelectWindow.preselectedServer = ServerSelectWindow.GetPreSelectServerID()
        
        -- if there isn't a pre-selected server or the pre-selected server isn't in the server list we will return false
        if  ServerSelectWindow.preselectedServer == -1 or
            ServerSelectWindow.serverList == nil or 
            ServerSelectWindow.serverList[ServerSelectWindow.preselectedServer] == nil
        then
            return false
        end

        -- set the realm that we are sending the player to
        if ServerSelectWindow.serverList[ServerSelectWindow.preselectedServer].orderPopulationDensity < ServerSelectWindow.serverList[ServerSelectWindow.preselectedServer].destructionPopulationDensity
        then
            ServerSelectWindow.preselectedServerRealm = ServerSelectWindow.ORDER_ONLY
        elseif ServerSelectWindow.serverList[ServerSelectWindow.preselectedServer].destructionPopulationDensity < ServerSelectWindow.serverList[ServerSelectWindow.preselectedServer].orderPopulationDensity
        then
            ServerSelectWindow.preselectedServerRealm = ServerSelectWindow.DESTRUCTION_ONLY
        -- else we have the same pop density so we'll randomly choose between the 2
        else
            -- randomly determine which server to choose from
            randRealmIndex = math.random(1, 2)
            if randRealmIndex == 1
            then
                ServerSelectWindow.preselectedServerRealm = ServerSelectWindow.ORDER_ONLY
            else
                ServerSelectWindow.preselectedServerRealm = ServerSelectWindow.DESTRUCTION_ONLY
            end
        end
        return true
    end

    return false
end

function ServerSelectWindow.GetPreSelectServerID()
    local imbalanceList = {}
    local imbalanceIndex = 1
    local highestImbalance = 0
    
    -- set the default server to -1
    imbalanceList[imbalanceIndex] = -1
    
    -- I need to find the server(s) with the largest population density imbalance
    for index, serverData in pairs(ServerSelectWindow.preselectedServerList)
    do
        -- if we have a server with a higher imbalance we have to reset everything
        if serverData.imbalance > highestImbalance
        then
            -- clear the imbalance list
            imbalanceList = {}
            -- reset the index
            imbalanceIndex = 1
            -- set the new highest imbalance
            highestImbalance = serverData.imbalance
            -- and add the new imbalance server's index to the list
            imbalanceList[imbalanceIndex] = index
            
        -- if we have a server with the same imbalance value we will add it to the list
        elseif serverData.imbalance == highestImbalance
        then
            imbalanceIndex = imbalanceIndex + 1
            imbalanceList[imbalanceIndex] = index
        end
    end

    -- randomly determine which server to choose from
    randListIndex = math.random(1, imbalanceIndex)

    return imbalanceList[randListIndex]
end

function ServerSelectWindow.InitPreSelect()
    -- do we need to show the pre-select window?
    -- if so this function call also populates the necessary variables
    if ServerSelectWindow.DeterminePreSelect() and GameData.Account.CharacterCreation.ShowPerSelectServer
    then
        ButtonSetText("ServerSelectWindowPreSelectedWindowAcceptButton", GetPregameString( StringTables.Pregame.LABEL_PRESELECT_ACCEPT ))
        ButtonSetText("ServerSelectWindowPreSelectedWindowDeclineButton", GetPregameString( StringTables.Pregame.LABEL_PRESELECT_DECLINE ))
        local realmText = L""
        if ServerSelectWindow.ORDER_ONLY == ServerSelectWindow.preselectedServerRealm
        then
            realmText = GetPregameString( StringTables.Pregame.LABEL_ORDER )
        elseif ServerSelectWindow.DESTRUCTION_ONLY == ServerSelectWindow.preselectedServerRealm
        then
            realmText = GetPregameString( StringTables.Pregame.LABEL_CHAOS )
        end
        local labelText = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_PRESELECT_MESSAGE, { realmText, ServerSelectWindow.serverList[ServerSelectWindow.preselectedServer].name } )
        LabelSetText("ServerSelectWindowPreSelectedWindowLabel", labelText )
    else
        WindowSetShowing("ServerSelectWindowPreSelectedWindow", false)
    end

    -- we only want to show the pre-select window if we meet the criteria the first time we come to the server screen
    GameData.Account.CharacterCreation.ShowPerSelectServer = false
end

function ServerSelectWindow.CancelPreSelect()
    WindowSetShowing("ServerSelectWindowPreSelectedWindow", false)
end

function ServerSelectWindow.SelectPreSelectedServer()
    WindowSetShowing("ServerSelectWindowPreSelectedWindow", false)
    -- set the pre-selected realm
    PregameSetPreSelectedServerRealm(ServerSelectWindow.preselectedServerRealm)
    SelectServer(ServerSelectWindow.serverList[ServerSelectWindow.preselectedServer].id)
end

-- server population density is now sent down from the server: 0 = low, 1 = med, 2 = high, 2 & a queue = full
function ServerSelectWindow.GetPopulationLabel(populationDensity, populationQueue)
    local popLabel = L""
    if (populationDensity == 0)
    then
        popLabel = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_LOW )
    elseif (populationDensity == 1)
    then
        popLabel = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_MED )
    elseif (populationDensity == 2)
    then
        if populationQueue == 0
        then
            popLabel = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_HIGH )
        else
            popLabel = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_FULL, { L""..populationQueue } )
        end
    end

    return popLabel
end

function ServerSelectWindow.GetConcurrentPop(a)
    if (a.orderPopulationDensity == a.destructionPopulationDensity)
    then
        return 0
    elseif (a.orderPopulationDensity < a.destructionPopulationDensity)
    then
        return a.orderPopulationDensity - a.destructionPopulationDensity
    else
        return a.destructionPopulationDensity - a.orderPopulationDensity
    end
end

-- Tooltip functions --
function ServerSelectWindow.CreateTooltip(window, text)
    Tooltips.CreateTextOnlyTooltip( window, text )
    Tooltips.AnchorTooltip( Tooltips.ANCHOR_WINDOW_LEFT)
end

function ServerSelectWindow.ShowLocationTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tableIndex = ListBoxGetDataIndex("ServerSelectWindowList", slot)
    local tooltipString = L""
    
    if ("STR_REGION_NORTHAMERICA" == ServerSelectWindow.serverList[tableIndex].region)
    then
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_NORTH_AMERICA ) } )
    elseif ("STR_REGION_OCEANIC" == ServerSelectWindow.serverList[tableIndex].region)
    then
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_OCEANIC ) } )
    elseif ("STR_REGION_OCEANIC2" == ServerSelectWindow.serverList[tableIndex].region)
    then
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_OCEANIC2 ) } )
    elseif ("STR_REGION_RUSSIA" == ServerSelectWindow.serverList[tableIndex].region)
    then
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_RUSSIA ) } )
    elseif ("STR_REGION_TAIWAN" == ServerSelectWindow.serverList[tableIndex].region)
    then
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_LOCATION_TAIWAN ) } )
    else
        return
    end

    ServerSelectWindow.CreateTooltip(windowName, tooltipString)
end

function ServerSelectWindow.ShowLanguageTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tableIndex = ListBoxGetDataIndex("ServerSelectWindowList", slot)
    local tooltipString = L""
    
    tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_LANGUAGE_TOOLTIP, { GetStringFromTable( "ServerLanguage", ServerSelectWindow.serverList[tableIndex].language) } )

    ServerSelectWindow.CreateTooltip(windowName, tooltipString)
end

function ServerSelectWindow.ShowRuleSetTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tableIndex = ListBoxGetDataIndex("ServerSelectWindowList", slot)
    local tooltipString = L""
    
    if (ServerSelectWindow.serverList[tableIndex].rulesetCore)
    then
        tooltipString = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_RULE_SET_CORE_TOOLTIP )
    elseif (ServerSelectWindow.serverList[tableIndex].rulesetOpenRvR) and (ServerSelectWindow.serverList[tableIndex].rulesetRolePlaying)
    then
        tooltipString = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_RULE_SET_OPEN_RVR_RP_TOOLTIP )
    elseif (ServerSelectWindow.serverList[tableIndex].rulesetOpenRvR)
    then
        tooltipString = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_RULE_SET_OPEN_RVR_TOOLTIP )
    elseif (ServerSelectWindow.serverList[tableIndex].rulesetRolePlaying)
    then
        tooltipString = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_RULE_SET_ROLE_PLAY_TOOLTIP )
    else
        return
    end

    ServerSelectWindow.CreateTooltip(windowName, tooltipString)
end

-- server population density is now sent down from the server: 0 = low, 1 = med, 2 = high, 2 & a queue = full
function ServerSelectWindow.GetTooltipPopulationLabel(populationDensity)
    local popLabel = L""
    if (populationDensity == 0)
    then
        popLabel = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_TOOLTIP_LOW )
    elseif (populationDensity == 1)
    then
        popLabel = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_TOOLTIP_MEDIUM )
    elseif (populationDensity == 2)
    then
        popLabel = GetPregameString( StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_TOOLTIP_HIGH )
    end

    return popLabel
end

function ServerSelectWindow.ShowOrderPopulationTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tableIndex = ListBoxGetDataIndex("ServerSelectWindowList", slot)
    local tooltipString = L""

    -- if there isn't a queue then we know it isn't a full server
    if (ServerSelectWindow.serverList[tableIndex].orderPopulationQueue == 0)
    then
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_TOOLTIP, { ServerSelectWindow.GetTooltipPopulationLabel(ServerSelectWindow.serverList[tableIndex].orderPopulationDensity), GetPregameString( StringTables.Pregame.LABEL_ORDER ) } )
    else
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_QUEUE_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_ORDER ), L""..ServerSelectWindow.serverList[tableIndex].orderPopulationQueue } )
    end
    ServerSelectWindow.CreateTooltip(windowName, tooltipString)
end

function ServerSelectWindow.ShowDestructionPopulationTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tableIndex = ListBoxGetDataIndex("ServerSelectWindowList", slot)
    local tooltipString = L""

    -- if there isn't a queue then we know it isn't a full server
    if (ServerSelectWindow.serverList[tableIndex].destructionPopulationQueue == 0)
    then
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_POPULATION_TOOLTIP, { ServerSelectWindow.GetTooltipPopulationLabel(ServerSelectWindow.serverList[tableIndex].destructionPopulationDensity), GetPregameString( StringTables.Pregame.LABEL_CHAOS ) } )
    else
        tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_SERVER_SELECT_QUEUE_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_CHAOS ), L""..ServerSelectWindow.serverList[tableIndex].destructionPopulationQueue } )
    end
    ServerSelectWindow.CreateTooltip(windowName, tooltipString)
end

function ServerSelectWindow.ShowOrderIconButtonTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_POPULATION_BONUS_BUTTON_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_ORDER ) } )
    ServerSelectWindow.CreateTooltip(windowName, tooltipString)
end

function ServerSelectWindow.ShowDestructionIconButtonTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_POPULATION_BONUS_BUTTON_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_CHAOS ) } )
    ServerSelectWindow.CreateTooltip(windowName, tooltipString)
end

function ServerSelectWindow.ShowOrderIconTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tableIndex = ListBoxGetDataIndex("ServerSelectWindowList", slot)

    if ServerSelectWindow.serverList[tableIndex].orderBonus ~= 0
    then
        local tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_POPULATION_BONUS_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_ORDER ) } )
        ServerSelectWindow.CreateTooltip(windowName, tooltipString)
    end
end

function ServerSelectWindow.ShowDestructionIconTooltip(flags, x, y)
    local windowName = SystemData.ActiveWindow.name
    local slot = WindowGetId( windowName )
    local tableIndex = ListBoxGetDataIndex("ServerSelectWindowList", slot)

    if ServerSelectWindow.serverList[tableIndex].destructionBonus ~= 0
    then
        local tooltipString = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_POPULATION_BONUS_TOOLTIP, { GetPregameString( StringTables.Pregame.LABEL_CHAOS ) } )
        ServerSelectWindow.CreateTooltip(windowName, tooltipString)
    end
end

function ServerSelectWindow.GetPopBonusServer()
    -- we now only want to show the redirect / population bonus servers if the player has no characters
    if ((#ServerSelectWindow.popBonusServers ~= 0) and (not ServerSelectWindow.HasCharacters()))
    then
        local randRealmIndex = math.random(1, #ServerSelectWindow.popBonusServers)
        return ServerSelectWindow.popBonusServers[randRealmIndex]
    end

    return -1
end

function ServerSelectWindow.HasTrialServer()
    -- we now only want to show the redirect / population bonus servers if the player has no characters
    return (#ServerSelectWindow.trialUserServers ~= 0 and not ServerSelectWindow.HasCharacters())
end

function ServerSelectWindow.GetTrialUserServer()
    -- we now only want to show the redirect / population bonus servers if the player has no characters
    if ( ServerSelectWindow.HasTrialServer() )
    then
        local randRealmIndex = math.random(1, #ServerSelectWindow.trialUserServers)
        return ServerSelectWindow.trialUserServers[randRealmIndex]
    end

    return -1
end

-- I'm going to keep this function in case the way to determine the pop bonus server changes again
function ServerSelectWindow.IsPopBonusServer()
    return ServerSelectWindow.serverList[ServerSelectWindow.selectedServer].redirect
end

function ServerSelectWindow.ShowPopBonusServer(bPreSelectPopup)
    if ServerSelectWindow.DeterminePreSelect() and GameData.Account.CharacterCreation.ShowPerSelectServer
    then
        ServerSelectWindow.popBonusCancelMeansCancel = bPreSelectPopup
        WindowSetShowing("ServerSelectWindowPopBonusWindow", true)
        ButtonSetText("ServerSelectWindowPopBonusWindowAcceptButton", GetPregameString( StringTables.Pregame.LABEL_PRESELECT_ACCEPT ))
        ButtonSetText("ServerSelectWindowPopBonusWindowDeclineButton", GetPregameString( StringTables.Pregame.LABEL_PRESELECT_DECLINE ))

        ServerSelectWindow.popBonusServer = ServerSelectWindow.GetPopBonusServer()
        local selectedServer = ServerSelectWindow.serverList[ServerSelectWindow.popBonusServer]
        local realmText = L""
        local labelText = L""

        -- if we have a server with both realms on a bonus we will provide the user with the option to go to either realm if
        -- they choose that server, with the new redirect flag there could possibly be a case where we have no bonuses on the server
        if (((selectedServer.orderBonus ~= 0) and (selectedServer.destructionBonus ~= 0)) or
            ((selectedServer.orderBonus == 0) and (selectedServer.destructionBonus == 0)))
        then
            labelText = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_POPULATION_BONUS_POPUP_BOTH_REALMS, { selectedServer.name } )
            ServerSelectWindow.popBonusServerRealm = ServerSelectWindow.BOTH_REALM_OPTIONS
        -- otherwise we will only allow them to go to the correct realm if they choose to go to the server
        else
            if (selectedServer.destructionBonus ~= 0)
            then
                realmText = GetPregameString( StringTables.Pregame.LABEL_CHAOS )
                ServerSelectWindow.popBonusServerRealm = ServerSelectWindow.DESTRUCTION_ONLY
            else
                realmText = GetPregameString( StringTables.Pregame.LABEL_ORDER )
                ServerSelectWindow.popBonusServerRealm = ServerSelectWindow.ORDER_ONLY
            end
            labelText = GetStringFormatFromTable( "Pregame", StringTables.Pregame.LABEL_POPULATION_BONUS_POPUP_ONE_REALM, { realmText, selectedServer.name } )
        end

        -- we need to notify the character select state that we have been auto logged in so we will set it here
        ServerSelectWindow.autoLoggedIn = true

        LabelSetText("ServerSelectWindowPopBonusWindowLabel", labelText )
        ServerSelectWindow.SelectPopBonusServer()
        -- we only want to show the pre-select window if we meet the criteria the first time we come to the server screen
        GameData.Account.CharacterCreation.ShowPerSelectServer = false
        -- we will hide the server select window because we don't want the new user seeing it while they are being redirected
        WindowSetShowing("ServerSelectWindow", false)
    else
        -- since there we aren't showing the population bonus servers we will hide the window
        WindowSetShowing("ServerSelectWindowPopBonusWindow", false)
    end
end

function ServerSelectWindow.CancelPopBonus()
    WindowSetShowing("ServerSelectWindowPopBonusWindow", false)

    -- if we were offering an option after they choose a server then we will continue to their selected server if they canceled
    if not ServerSelectWindow.popBonusCancelMeansCancel
    then
        ServerSelectWindow.SelectServer()
    end
end

function ServerSelectWindow.SelectPopBonusServer()
    WindowSetShowing("ServerSelectWindowPopBonusWindow", false)
    -- we will set the selected server to this server now that it has been accepted and send it back through the logic
    -- this is to assure all the proper popups are seen
    ServerSelectWindow.selectedServer = ServerSelectWindow.popBonusServer
    -- set the realm options for character creation, could be both if both realms have a population bonus
    PregameSetPreSelectedServerRealm(ServerSelectWindow.popBonusServerRealm)
    local server = ServerSelectWindow.serverList[ServerSelectWindow.popBonusServer]
    -- set the realm bonus values for the server
    PregameSetServerRealmBonuses( ServerSelectWindow.serverList[ServerSelectWindow.popBonusServer].orderBonus, ServerSelectWindow.serverList[ServerSelectWindow.popBonusServer].destructionBonus )
    -- and act as if this was the server that was choosen from the server select originally
    ServerSelectWindow.SelectServerButton()
end

-- this function is used to determine if the player is allowed to connect to the server they selected
function ServerSelectWindow.VerifyServer()
    -- if the server is 
    local server = ServerSelectWindow.serverList[ServerSelectWindow.selectedServer]
    if ( (server.legacy or server.retired ) and 
         (server.characterCount == 0))
    then
        ButtonSetDisabledFlag( "ServerSelectWindowSelectButton", true )
    else
        ButtonSetDisabledFlag( "ServerSelectWindowSelectButton", false )
    end
end

function ServerSelectWindow.OnToggleLegacy()
    ServerSelectWindow.showLegacyServers = not ServerSelectWindow.showLegacyServers
    ButtonSetPressedFlag( "ServerSelectWindowShowLegacy", ServerSelectWindow.showLegacyServers )
    ServerSelectWindow.RefreshList()
end

-- we need to have trial servers and the player needs to be flagged as a trial account
function ServerSelectWindow.SendToTrialUserServer()
    if (ServerSelectWindow.HasTrialServer() and 
        ServerSelectWindow.trialPlayer and 
        GameData.Account.CharacterCreation.ShowPerSelectServer)
    then
        return true
    end
    
    return false
end    
-- this is where we determine if we want to send the user to a trial server or not
function ServerSelectWindow.SelectTrialUserServer()
    ServerSelectWindow.trialPlayerServer = ServerSelectWindow.GetTrialUserServer()
    if ((ServerSelectWindow.trialPlayer) and 
        (not ServerSelectWindow.buddiedPlayer) and 
        (ServerSelectWindow.trialPlayerServer ~= -1) and 
        GameData.Account.CharacterCreation.ShowPerSelectServer)
    then
        -- we will hide the server select window because we don't want the new user seeing it while they are being redirected
        WindowSetShowing("ServerSelectWindow", false)

        -- we will set the selected server to this server now that it has been accepted and send it back through the logic
        -- this is to assure all the proper popups are seen
        ServerSelectWindow.selectedServer = ServerSelectWindow.trialPlayerServer
        local server = ServerSelectWindow.serverList[ServerSelectWindow.trialPlayerServer]
        -- set the realm bonus values for the server
        PregameSetServerRealmBonuses( server.orderBonus, server.destructionBonus )
        -- and act as if this was the server that was choosen from the server select originally
        ServerSelectWindow.SelectServerButton()
        -- only push a trial player to the trial servers once a session
        GameData.Account.CharacterCreation.ShowPerSelectServer = false
    end
end

function ServerSelectWindow.ShowUpgradeOption()
    EA_TrialAlertWindow.Show(SystemData.TrialAlert.ALERT_SERVER)
end
